<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>缓冲区监控 - Netty See</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        .buffer-card {
            transition: transform 0.2s;
        }
        .buffer-card:hover {
            transform: translateY(-2px);
        }
        .progress-bar-custom {
            transition: width 0.3s ease;
        }
        .metric-value {
            font-size: 1.5rem;
            font-weight: bold;
        }
        .buffer-content {
            font-family: 'Courier New', monospace;
            background-color: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 0.375rem;
            padding: 0.5rem;
            max-height: 200px;
            overflow-y: auto;
        }
        .chart-container {
            position: relative;
            height: 300px;
        }
    </style>
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="/">
                <i class="fas fa-network-wired"></i> Netty See
            </a>
            <div class="navbar-nav ms-auto">
                <a class="nav-link" href="/">首页</a>
                <a class="nav-link" href="/channels">Channels</a>
                <a class="nav-link" href="/eventloops">Event Loops</a>
                <a class="nav-link active" href="/buffers">缓冲区</a>
                <a class="nav-link" href="/performance">Performance</a>
                <a class="nav-link" href="/errors">错误分析</a>
            </div>
        </div>
    </nav>

    <div class="container mt-4">
        <div class="row">
            <div class="col-12">
                <h1 class="mb-4">
                    <i class="fas fa-memory"></i> 缓冲区监控
                    <button class="btn btn-primary btn-sm ms-3" onclick="refreshBuffers()">
                        <i class="fas fa-sync-alt"></i> 刷新
                    </button>
                </h1>
            </div>
        </div>

        <!-- 总体统计 -->
        <div class="row mb-4">
            <div class="col-md-3">
                <div class="card text-white bg-primary">
                    <div class="card-body text-center">
                        <i class="fas fa-database fa-2x mb-2"></i>
                        <div class="metric-value" id="totalBuffers">0</div>
                        <div>总缓冲区数</div>
                    </div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card text-white bg-success">
                    <div class="card-body text-center">
                        <i class="fas fa-chart-line fa-2x mb-2"></i>
                        <div class="metric-value" id="totalCapacity">0</div>
                        <div>总容量 (KB)</div>
                    </div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card text-white bg-warning">
                    <div class="card-body text-center">
                        <i class="fas fa-percentage fa-2x mb-2"></i>
                        <div class="metric-value" id="avgUtilization">0%</div>
                        <div>平均利用率</div>
                    </div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card text-white bg-info">
                    <div class="card-body text-center">
                        <i class="fas fa-memory fa-2x mb-2"></i>
                        <div class="metric-value" id="directBuffers">0</div>
                        <div>直接缓冲区</div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 缓冲区列表 -->
        <div class="row">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">
                            <i class="fas fa-list"></i> 缓冲区详情
                            <span class="badge bg-secondary ms-2" id="bufferCount">0</span>
                        </h5>
                    </div>
                    <div class="card-body">
                        <div id="bufferList" class="row">
                            <div class="col-12 text-center text-muted">
                                <i class="fas fa-spinner fa-spin fa-2x mb-3"></i>
                                <p>正在加载缓冲区信息...</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 缓冲区使用趋势图 -->
        <div class="row mt-4">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">
                            <i class="fas fa-chart-area"></i> 缓冲区使用趋势
                        </h5>
                    </div>
                    <div class="card-body">
                        <div class="chart-container">
                            <canvas id="bufferTrendChart"></canvas>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 缓冲区详情模态框 -->
    <div class="modal fade" id="bufferDetailModal" tabindex="-1">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">
                        <i class="fas fa-info-circle"></i> 缓冲区详情
                    </h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body">
                    <div id="bufferDetailContent">
                        <!-- 详情内容将通过JavaScript填充 -->
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        let bufferTrendChart;
        let refreshInterval;

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            initBufferTrendChart();
            loadBuffers();
            startAutoRefresh();
        });

        // 初始化趋势图
        function initBufferTrendChart() {
            const ctx = document.getElementById('bufferTrendChart').getContext('2d');
            bufferTrendChart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: [],
                    datasets: [{
                        label: '总容量 (KB)',
                        data: [],
                        borderColor: 'rgb(75, 192, 192)',
                        backgroundColor: 'rgba(75, 192, 192, 0.2)',
                        tension: 0.1
                    }, {
                        label: '已使用 (KB)',
                        data: [],
                        borderColor: 'rgb(255, 99, 132)',
                        backgroundColor: 'rgba(255, 99, 132, 0.2)',
                        tension: 0.1
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            beginAtZero: true,
                            title: {
                                display: true,
                                text: '容量 (KB)'
                            }
                        },
                        x: {
                            title: {
                                display: true,
                                text: '时间'
                            }
                        }
                    },
                    plugins: {
                        legend: {
                            display: true,
                            position: 'top'
                        }
                    }
                }
            });
        }

        // 加载缓冲区信息
        function loadBuffers() {
            fetch('/api/netty/buffers')
                .then(response => response.json())
                .then(data => {
                    updateBufferStats(data);
                    renderBufferList(data);
                    updateTrendChart(data);
                })
                .catch(error => {
                    console.error('加载缓冲区信息失败:', error);
                    showError('加载缓冲区信息失败: ' + error.message);
                });
        }

        // 更新统计信息
        function updateBufferStats(buffers) {
            const totalBuffers = buffers.length;
            const totalCapacity = buffers.reduce((sum, buffer) => sum + (buffer.capacity || 0), 0);
            const directBuffers = buffers.filter(buffer => buffer.isDirect).length;
            const avgUtilization = totalBuffers > 0 ? 
                buffers.reduce((sum, buffer) => sum + (buffer.memoryUtilization || 0), 0) / totalBuffers : 0;

            document.getElementById('totalBuffers').textContent = totalBuffers;
            document.getElementById('totalCapacity').textContent = Math.round(totalCapacity / 1024);
            document.getElementById('avgUtilization').textContent = Math.round(avgUtilization) + '%';
            document.getElementById('directBuffers').textContent = directBuffers;
            document.getElementById('bufferCount').textContent = totalBuffers;
        }

        // 渲染缓冲区列表
        function renderBufferList(buffers) {
            const container = document.getElementById('bufferList');
            
            if (buffers.length === 0) {
                container.innerHTML = `
                    <div class="col-12 text-center text-muted">
                        <i class="fas fa-inbox fa-3x mb-3"></i>
                        <p>暂无缓冲区信息</p>
                    </div>
                `;
                return;
            }

            container.innerHTML = buffers.map(buffer => `
                <div class="col-md-6 col-lg-4 mb-3">
                    <div class="card buffer-card h-100">
                        <div class="card-header d-flex justify-content-between align-items-center">
                            <h6 class="mb-0">
                                <i class="fas fa-microchip"></i> ${buffer.channelId}
                            </h6>
                            <span class="badge ${buffer.isDirect ? 'bg-success' : 'bg-secondary'}">
                                ${buffer.isDirect ? 'Direct' : 'Heap'}
                            </span>
                        </div>
                        <div class="card-body">
                            <div class="mb-2">
                                <small class="text-muted">应用:</small>
                                <span class="fw-bold">${buffer.applicationName || 'N/A'}</span>
                            </div>
                            
                            <div class="mb-2">
                                <small class="text-muted">容量:</small>
                                <span>${formatBytes(buffer.capacity)}</span>
                                <span class="text-muted">/ ${formatBytes(buffer.maxCapacity || buffer.capacity)}</span>
                            </div>
                            
                            <div class="mb-2">
                                <small class="text-muted">可读/可写:</small>
                                <span class="text-success">${formatBytes(buffer.readableBytes)}</span> /
                                <span class="text-primary">${formatBytes(buffer.writableBytes)}</span>
                            </div>
                            
                            <div class="mb-2">
                                <small class="text-muted">索引:</small>
                                <span>R:${buffer.readerIndex} W:${buffer.writerIndex}</span>
                            </div>
                            
                            <div class="mb-3">
                                <small class="text-muted">利用率:</small>
                                <div class="progress mt-1">
                                    <div class="progress-bar progress-bar-custom ${getUtilizationColor(buffer.memoryUtilization)}" 
                                         style="width: ${buffer.memoryUtilization || 0}%">
                                        ${Math.round(buffer.memoryUtilization || 0)}%
                                    </div>
                                </div>
                            </div>
                            
                            <div class="d-flex justify-content-between">
                                <small class="text-muted">引用计数: ${buffer.refCount || 1}</small>
                                <button class="btn btn-sm btn-outline-primary" 
                                        onclick="showBufferDetail('${buffer.channelId}')">
                                    详情
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            `).join('');
        }

        // 更新趋势图
        function updateTrendChart(buffers) {
            const now = new Date();
            const timeLabel = now.toLocaleTimeString();
            
            const totalCapacity = buffers.reduce((sum, buffer) => sum + (buffer.capacity || 0), 0) / 1024;
            const usedCapacity = buffers.reduce((sum, buffer) => 
                sum + ((buffer.capacity || 0) - (buffer.writableBytes || 0)), 0) / 1024;

            // 添加新数据点
            bufferTrendChart.data.labels.push(timeLabel);
            bufferTrendChart.data.datasets[0].data.push(totalCapacity);
            bufferTrendChart.data.datasets[1].data.push(usedCapacity);

            // 只保留最近20个数据点
            if (bufferTrendChart.data.labels.length > 20) {
                bufferTrendChart.data.labels.shift();
                bufferTrendChart.data.datasets[0].data.shift();
                bufferTrendChart.data.datasets[1].data.shift();
            }

            bufferTrendChart.update('none');
        }

        // 显示缓冲区详情
        function showBufferDetail(channelId) {
            fetch(`/api/netty/channels/${channelId}/buffer`)
                .then(response => response.json())
                .then(buffer => {
                    const content = `
                        <div class="row">
                            <div class="col-md-6">
                                <h6>基本信息</h6>
                                <table class="table table-sm">
                                    <tr><td>Channel ID:</td><td>${buffer.channelId}</td></tr>
                                    <tr><td>应用名称:</td><td>${buffer.applicationName || 'N/A'}</td></tr>
                                    <tr><td>缓冲区类型:</td><td>${buffer.bufferType || (buffer.isDirect ? 'DirectByteBuf' : 'HeapByteBuf')}</td></tr>
                                    <tr><td>是否直接缓冲区:</td><td>${buffer.isDirect ? '是' : '否'}</td></tr>
                                    <tr><td>是否有数组支持:</td><td>${buffer.hasArray ? '是' : '否'}</td></tr>
                                    <tr><td>引用计数:</td><td>${buffer.refCount || 1}</td></tr>
                                </table>
                            </div>
                            <div class="col-md-6">
                                <h6>容量信息</h6>
                                <table class="table table-sm">
                                    <tr><td>当前容量:</td><td>${formatBytes(buffer.capacity)}</td></tr>
                                    <tr><td>最大容量:</td><td>${formatBytes(buffer.maxCapacity || buffer.capacity)}</td></tr>
                                    <tr><td>可读字节:</td><td>${formatBytes(buffer.readableBytes)}</td></tr>
                                    <tr><td>可写字节:</td><td>${formatBytes(buffer.writableBytes)}</td></tr>
                                    <tr><td>读索引:</td><td>${buffer.readerIndex}</td></tr>
                                    <tr><td>写索引:</td><td>${buffer.writerIndex}</td></tr>
                                </table>
                            </div>
                        </div>
                        
                        <div class="row mt-3">
                            <div class="col-12">
                                <h6>统计信息</h6>
                                <table class="table table-sm">
                                    <tr>
                                        <td>总读取次数:</td><td>${buffer.totalReads || 0}</td>
                                        <td>总写入次数:</td><td>${buffer.totalWrites || 0}</td>
                                    </tr>
                                    <tr>
                                        <td>分配次数:</td><td>${buffer.totalAllocations || 0}</td>
                                        <td>释放次数:</td><td>${buffer.totalDeallocations || 0}</td>
                                    </tr>
                                    <tr>
                                        <td>内存利用率:</td><td>${Math.round(buffer.memoryUtilization || 0)}%</td>
                                        <td>最后更新:</td><td>${buffer.lastUpdateTime || 'N/A'}</td>
                                    </tr>
                                </table>
                            </div>
                        </div>
                        
                        ${buffer.content ? `
                        <div class="row mt-3">
                            <div class="col-12">
                                <h6>缓冲区内容 <small class="text-muted">(前256字节)</small></h6>
                                <div class="buffer-content">
                                    ${escapeHtml(buffer.content)}
                                </div>
                            </div>
                        </div>
                        ` : ''}
                    `;
                    
                    document.getElementById('bufferDetailContent').innerHTML = content;
                    new bootstrap.Modal(document.getElementById('bufferDetailModal')).show();
                })
                .catch(error => {
                    console.error('获取缓冲区详情失败:', error);
                    showError('获取缓冲区详情失败: ' + error.message);
                });
        }

        // 刷新缓冲区信息
        function refreshBuffers() {
            loadBuffers();
        }

        // 开始自动刷新
        function startAutoRefresh() {
            refreshInterval = setInterval(loadBuffers, 5000); // 每5秒刷新一次
        }

        // 停止自动刷新
        function stopAutoRefresh() {
            if (refreshInterval) {
                clearInterval(refreshInterval);
            }
        }

        // 工具函数
        function formatBytes(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        function getUtilizationColor(utilization) {
            if (utilization < 50) return 'bg-success';
            if (utilization < 80) return 'bg-warning';
            return 'bg-danger';
        }

        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        function showError(message) {
            const container = document.getElementById('bufferList');
            container.innerHTML = `
                <div class="col-12">
                    <div class="alert alert-danger" role="alert">
                        <i class="fas fa-exclamation-triangle"></i> ${message}
                    </div>
                </div>
            `;
        }

        // 页面卸载时停止自动刷新
        window.addEventListener('beforeunload', stopAutoRefresh);
    </script>
</body>
</html>